<template>
  <div id="container" ref="container" />
</template>
<script>
import * as monaco from 'monaco-editor';
import { emmetHTML, emmetCSS, emmetJSX } from 'emmet-monaco-es'
import { getData, getDataArr, setDataArr } from '@/utils/auth'

import { mapGetters } from 'vuex';
export default {
  name: "XMonacoEditor",
  props: {
    item: {
      type: Object,
      default: () => {
        return {
          codes: "",
          language: "html",
          diff: false,
          id: null
        };
      },
    },
    widthChange: {
      type: Boolean,
      default: true
    },
    editorOptions: {
      type: Object,
      default: function () {
        return {
          selectOnLineNumbers: true,
          roundedSelection: false,
          readOnly: false, // 只读
          cursorStyle: "line", // 光标样式
          automaticLayout: false, // 自动布局
          glyphMargin: true, // 字形边缘
          useTabStops: false,
          fontSize: 17, // 字体大小
          autoIndent: true, // 自动布局
          number: ''
          // quickSuggestionsDelay: 500,   //代码提示延时
        };
      },
    },
  },
  data() {
    return {
      codesCopy: null,
      cursorPosition: null,
      monacoEditor: null
    };
  },
  computed: {
    ...mapGetters(["theme", "fontSize", "isFullScreen"]),
    containerDom() {
      return this.$refs.container;
    },
    changeid() {
      return this.item.id
    }
  },
  watch: {
    theme() {
      this.initEditor();
    },
    fontSize() {
      this.initEditor();
    },
    isFullScreen() {
      this.initEditor();
    },
    changeid() {
      this.initEditor(true);
    },
    widthChange() {
      this.setEditorWidth();
      this.monacoEditor.layout();
    }
  },
  created() {
    this.number = this.$route.params && this.$route.params.id
  },
  mounted() {
    this.initEditor();
    // 编辑器随窗口自适应
    window.addEventListener("resize", () => {
      this.setEditorWidth();
      this.monacoEditor.layout();
    });
  },
  methods: {
    initEditor(diff) {
      let self = this;
      if (!self.item.diff && !diff) {
        self.containerDom.innerHTML = "";
        monaco.editor.defineTheme('BlackTheme', {
          base: 'vs-dark',
          inherit: true,
          rules: [{ background: '#3e414a' }],
          colors: {
            // 相关颜色属性配置
            'editor.background': '#202735'
          }
        });
        //设置自定义主题
        monaco.editor.setTheme('BlackTheme');
        self.monacoEditor = monaco.editor.create(self.containerDom, {
          value: self.item.codes,
          language: self.item.language,
          theme: 'BlackTheme', // vs, hc-black, or vs-dark
          wordWrap: "on",
          formatOnType: true,
          formatOnPaste: true,
          fontSize: self.fontSize,
          editorOptions: self.editorOptions,
          minimap: {
            // 不要小地图
            enabled: false,
          },
        });
        // 自动补全扩展
        self.emmetExtend(self.item.language, monaco)
        self.$emit("onMounted", self.monacoEditor); // 编辑器创建完成回调
        self.monacoEditor.onDidChangeModelContent(() => {
          this.changeModelContentFunc()
        });
        // 监听编辑器滚动事件，获取当前滚动距离
        self.monacoEditor.onDidScrollChange(function (event) {
          const currentFile = getData();
          const fileArr = JSON.parse(getDataArr());
          for (let i = 0; i < fileArr[self.number].length; i++ ) {
            if (fileArr[self.number][i].key === currentFile) {
              fileArr[self.number][i].position = event.scrollTop
            }
          }
          setDataArr(JSON.stringify(fileArr))
        })
        // 监听编辑器当前行号
        self.monacoEditor.onDidChangeCursorPosition(e => {
          this.cursorPosition = e.position;
        })
        // 监听cmd/ctrl+s
        self.monacoEditor.addCommand(
          monaco.KeyMod.CtrlCmd | monaco.KeyCode.KEY_S,
          function () {
            self.$emit("onCodeSave", self.item);
          }
        );
        // 设置编辑器的初始位置
        self.monacoEditor.setScrollTop(self.getEditorScrollTop())
      } else {
        self.containerDom.innerHTML = "";
        self.monacoEditor = monaco.editor.createDiffEditor(self.containerDom, {
          theme: self.theme,
          readOnly: true
        })
        self.emmetExtend(self.item.language, monaco)
        self.monacoEditor.setModel({
          original: monaco.editor.createModel(self.item.diffcode, self.item.language),
          modified: monaco.editor.createModel(self.item.contentcode, self.item.language)
        })
      }
    },
    initMonaco() {
      this.initEditor()
    },
    emmetExtend(lang, monaco) {
      const types = ['css', 'html', 'php', 'twig', 'javascript']
      if (types.includes(lang)) {
        if (lang === "css") {
          emmetCSS(monaco)
        } else if (lang === 'javascript') {
          emmetJSX(monaco)
        } else {
          emmetHTML(monaco, ['html', 'php', 'twig'])
        }
      }
    },
    // 获取当前打开的文件的位置
    getEditorScrollTop() {
      let top = 0;
      const currentFile = getData();
      const fileArr = JSON.parse(getDataArr())[this.number];
      for (let i = 0; i < fileArr.length; i++) {
        if (currentFile === fileArr[i].key) {
          top = fileArr[i].position || 0;
          break;
        }
      }
      return top;
    },
    changeModelContentFunc() {
      // 编辑器内容change事件
      this.codesCopy = this.monacoEditor.getValue();
      this.$set(this.item, "codes", this.monacoEditor.getValue());
      this.$set(this.item, "edit", true);
      this.$emit("onCodeChange", this.item);
    },
    setEditorWidth() {
      const codeMainExplorerWidth = document.querySelector('.code-main-explorer').clientWidth
      const componentListWidth = document.querySelector('.component-list').clientWidth
      const windowWith = window.document.documentElement.clientWidth
      const editorWidth = windowWith - codeMainExplorerWidth - componentListWidth;
      document.querySelector('.code-main-editor').style.width = `${editorWidth}px`;
    }
  }
};
</script>
<style scoped>
#container {
  height: calc(100vh - 100px);
  width: 100%;
  text-align: left;
}
</style>
